package com.ayz.gateway.core.rpc.dubbo;


import com.ayz.gateway.core.rpc.GenericReferenceProxyFactory;
import com.ayz.gateway.core.rpc.IGatewayApi;
import lombok.Data;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.InterfaceMaker;
import org.apache.dubbo.rpc.service.GenericService;
import org.objectweb.asm.Type;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName DubboGenericReferenceProxyFactory
 * @Description TODO:用于生成Dubbo远程调用的范化接口
 * @Author 快乐的星球
 * @Date 2023/5/6 21:29
 * @Version 1.0
 **/
@Data
public class DubboGenericReferenceProxyFactory implements GenericReferenceProxyFactory {
    /**
     * Dubbo服务范化服务
     */
    private final GenericService genericService;
    /**
     * RPC资源方法的名称
     */
    private final String rpcMethod;

    public DubboGenericReferenceProxyFactory(GenericService genericService, String rpcMethod) {
        this.genericService = genericService;
        this.rpcMethod = rpcMethod;
    }

    private final ConcurrentHashMap<String, IGatewayApi> iGatewayApiCache=new ConcurrentHashMap<>(1);
    @Override
    public IGatewayApi newInstance() {
        return iGatewayApiCache.computeIfAbsent(rpcMethod,k->{
            //范化调用代理
            DubboGenericReferenceProxy genericReferenceProxy=new DubboGenericReferenceProxy(genericService,rpcMethod);
            //CGLIB动态生成接口
            InterfaceMaker interfaceMaker=new InterfaceMaker();
            interfaceMaker.add(new Signature(rpcMethod, Type.getType(String.class),new Type[]{Type.getType(String.class)}),null);
            //因为网关无法持有服务提供者的具体API接口，所以这里动态生成一个
            //与 IGatewayApi绑定
            Class<?> rpcInterface = interfaceMaker.create();
            //动态代理生成代理对象
            Enhancer enhancer=new Enhancer();
            enhancer.setSuperclass(Object.class);
            enhancer.setInterfaces(new Class[]{rpcInterface,IGatewayApi.class});
            enhancer.setCallback(genericReferenceProxy);
            return (IGatewayApi) enhancer.create();
        });
    }
}
